package com.jeestudio.utils;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;

/**
 * 26/52进制与10进制互转工具类
 *
 * @author
 *
 * */
public class Decimal52 {
    private static final int LOWER_A = 97;
    private static final int LOWER_Z = 123;
    private static final int UPPER_A = 65;
    private static final int UPPER_Z = 91;
    private static final int ZERO = 48;
    private static final int NINE = 58;
    private static List<Character> C_LIST = new LinkedList<Character>();
    private static int charSize;

    /**
     * upperOnly 或 lowerOnly 为true时，表示26进制
     * upper和lower都为false时候表示52进制
     * upper和has
     */
    private Decimal52() {
        this(false, false, false);
    }

    private Decimal52(boolean upperOnly, boolean lowerOnly, boolean hasNum) {
        if (hasNum) {
            IntStream.range(ZERO, NINE).forEach((c) -> C_LIST.add((char) c));
        }
        if (upperOnly) {
            IntStream.range(UPPER_A, UPPER_Z).forEach(
                    (c) -> C_LIST.add((char) c));
        } else if (lowerOnly) {
            IntStream.range(LOWER_A, LOWER_Z).forEach(
                    (c) -> C_LIST.add((char) c));
        } else {
            IntStream.range(UPPER_A, UPPER_Z).forEach(
                    (c) -> C_LIST.add((char) c));
            IntStream.range(LOWER_A, LOWER_Z).forEach(
                    (c) -> C_LIST.add((char) c));
        }
        charSize = C_LIST.size();
    }

    /**
     * @version 1.0.0
     * @Description 10进制转26/52进制
     * @return
     * */
    public static String getDecimal(int num) {
        if (num < 0)
            return null;
        StringBuilder sb = new StringBuilder();
        if (num >= charSize) {
            sb.append(getDecimal(num / charSize));
        }
        int least = num % charSize;
        sb.append(C_LIST.get(least));

        return sb.toString();
    }

    /**
     * @version 1.1
     * @Description N进制转10进制<br/>
     *              null非法字符转换
     * @return
     * */
    public static BigDecimal getDecimalism(String str) {
        BigDecimal num = BigDecimal.valueOf(0);
        char[] cNum = str.toCharArray();
        int length = cNum.length;
        for (char c : cNum) {
            if (C_LIST.indexOf(c) < 0)
                return null;
            num = num.add(BigDecimal.valueOf(C_LIST.indexOf(c)).multiply(
                    BigDecimal.valueOf(Math.pow(charSize, (--length)))));
        }
        return num;
    }

    /**
     * @version 1.0.0
     * @Description 10进制转N进制
     * @return
     * */
    public static String getDecimal(BigDecimal num) {
        if (num.compareTo(BigDecimal.valueOf(0)) < 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        BigDecimal[] divideAndRemainder = num.divideAndRemainder(BigDecimal
                .valueOf(charSize));
        if (divideAndRemainder[0].intValue() > 0) {
            sb.append(getDecimal(divideAndRemainder[0]));
        }
        int least = divideAndRemainder[1].intValue();
        sb.append(C_LIST.get(least));

        return sb.toString();
    }

    /**
     * long 10进制转52进制
     * @param num
     * @return
     */
    public static String to52(long num){
        String code = Decimal52.getInstance().getDecimal((int)num);
        return code;
    }

    /**
     * 将52进制转10进制
     * @param code
     * @return
     */
    public static long to10(String code){
        return getDecimalism(code).longValue();
    }

    public static final Decimal52 getInstance(){
        return Decimal52Holder.INSTANCE;
    }

    static class Decimal52Holder{
        private static final Decimal52 INSTANCE = new Decimal52();
    }

//    public static void main(String [] args){
//        int test = -1;
//        String abc = Decimal52.getInstance().to52(test);
//        System.out.println("1-52得到的值：" + abc);
//        System.out.print("1-52-10得到的值：" + Decimal52.getInstance().to10(abc));
//    }
}
